<?php
/**
 * 命令模式
 * 将请求者和接收者解耦 , 解耦的方式为 耦合命令对象 .....
 *
 * 请求者 可以对应 多个命令对象
 * 每个命令对象关联一个 实际处理对象
 *
 * 思考:
 * 1.   为什么不直接在请求者中关联一个处理对象 ?
 *      回答: 如果直接关联 , 依赖或者强制关联 ,
 * */

/**
 * 请求者
 * */
class Request{
    # 聚合关系,聚合多个命令
    private $command = null;

    # 如果直接关联处理者呢 ?
    private $receive = null;

    public function __construct(Command $command)
    {
        $this->command = $command;
    }

    # 发送命令
    public function call(){
        $this->command->exec();
    }

    /**
     * 直接处理
     * 1.每个请求和处理方式都固定了
     * 2.如果需要修改处理方式,则必须在这里修改 , 违背开闭原则
     * 3.请求和处理算是多个职责 , 违背单一职责
     * 4.如果其他地方也需要这个处理方法 , 则不能很好的复用
     *
     *
     * 维护性差 复用性为 0
     * */
    public function sayHello(){
        echo 'now start working ';
    }

    /**
     * 直接关联处理对象
     * 1.假如某天更换了处理方法 , 变成了 sayBay , 你需要继续修改这里的代码 违反单一原则
     * 2.假如所有的 处理方法都 存在一个 exec 方法呢 ? 那是不是 , 即便更改业务操作 也不需要 更改下面的代码 ?
     *   确实可以复用 , 既然有统一的方法 , 那必然有统一的接口 , 那么接口名称叫做什么呢 ? 处理者?
     *   但是存在一个很严重的问题 , 实际的接收者只是一个正常对象呀,我为什么要去实现那些没用的接口
     *   你的交通方式是飞 , 我的交通方式是走路 , 为啥一定要我们统一 ? 是不是不合理 , 我就是我,我只能是我,所以我不会去实现其他的接口,也没有必要
     *
     * 改变了该类的特征 , 对原有的处理类有干扰 放弃
     * */
    public function sayHello2(){
        $this->receive->sayHello();     // ?
        $this->receive->exec();         // ?
    }


    /**
     * 总结 : 命令模式 , 只有添加命令对象的方案能够达到最优效果
     *          1. 将请求者 和 处理者分离
     *          2. 不影响处理者的一分一毫
     *          3. 命令层目的就是去统一处理层的业务方法 , 如果业务层都是统一方案 , 那么可以考虑不使用对应命令
     * */
}
/**
 * 接收者
 * */
class Receive{
    public function sayHello(){
        echo 'now start working ';
    }
}

/**
 * 命令
 * */
class Command{
    # 这里为关联关系 , 一个命令关联一个接收者
    private $receive = null;

    public function __construct()
    {
        $this->receive = new Receive();
    }

    public function exec(){
        $this->receive->sayHello();
    }
}

# 注入不同的命令对象
$request = new Request(new Command());

$request->call();